<template>
  <div class="publish-container">
    <el-card>
      <!-- 头部 -->
      <div slot="header">
        <el-breadcrumb separator-class="el-icon-arrow-right">
          <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
          <el-breadcrumb-item>
            {{ articleId ? '修改' : '发布' + '内容' }}
          </el-breadcrumb-item>
        </el-breadcrumb>
      </div>
      <!-- 表单 -->
      <el-form
        label-width="120px"
        :model="articleForm"
        :rules="articleRules"
        ref="articleDom"
      >
        <el-form-item label="标题：" prop="title">
          <el-input
            v-model="articleForm.title"
            placeholder="请输入文章标题"
            style="width: 400px"
          ></el-input>
        </el-form-item>
        <el-form-item label="频道：" prop="channel_id">
          <AllChannels v-model="articleForm.channel_id" />
        </el-form-item>
        <el-form-item label="封面：" prop="cover">
          <el-radio-group
            v-model="articleForm.cover.type"
            @change="imageTypeChange"
          >
            <el-radio :label="1">单图</el-radio>
            <el-radio :label="3">三图</el-radio>
            <el-radio :label="0">无图</el-radio>
            <el-radio :label="-1">自动</el-radio>
          </el-radio-group>
          <!-- 上传 -->
          <el-upload
            v-if="articleForm.cover.type === 1 || articleForm.cover.type === 3"
            ref="imgageUpload"
            :action="baseURL + '/v1_0/upload'"
            name="image"
            :headers="{ Authorization: `Bearer ${token}` }"
            list-type="picture-card"
            :limit="articleForm.cover.type"
            :on-success="imageUploadSuccess"
            :on-error="imageUploadError"
            :on-preview="handlePictureCardPreview"
            :on-remove="imageUploadRemove"
            :on-exceed="imageUploadExceed"
            :file-list="fileList"
          >
            <i class="el-icon-plus"></i>
          </el-upload>
          <!-- dialog 弹出层 -->
          <el-dialog :visible.sync="dialogVisible">
            <img width="100%" :src="dialogImageUrl" alt="" />
          </el-dialog>
        </el-form-item>
        <el-form-item label="内容：" prop="content">
          <div style="border: 1px solid #ccc">
            <Toolbar
              style="border-bottom: 1px solid #ccc"
              :editor="editor"
              :defaultConfig="toolbarConfig"
              :mode="mode"
            />
            <Editor
              style="height: 500px; overflow-y: hidden"
              v-model="articleForm.content"
              :defaultConfig="editorConfig"
              :mode="mode"
              @onCreated="onCreated"
            />
          </div>
        </el-form-item>
        <el-form-item label="">
          <template v-if="articleId">
            <el-button type="primary" @click="_modifiArticle(false)">
              修改文章
            </el-button>
            <el-button @click="_modifiArticle(true)">存入草稿</el-button>
          </template>
          <template v-else>
            <el-button type="primary" @click="_publicArticle(false)">
              发布文章
            </el-button>
            <el-button @click="_publicArticle(true)">存入草稿</el-button>
          </template>
        </el-form-item>
      </el-form>
    </el-card>
  </div>
</template>

<script>
import { baseURL } from '@/utils/request'
import { mapGetters } from 'vuex'
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import {
  publishArticle,
  getArticleDetail,
  modifiArticleDetail,
} from '@/api/article'

export default {
  name: 'PublishPage',
  props: {
    articleId: {
      type: String,
    },
  },
  components: {
    Editor,
    Toolbar,
  },
  data() {
    // #自定义图片校验规则
    const checkCoverFn = (rule, value, cb) => {
      // console.log('v', rule, value, cb)
      if (value.type === 1) {
        if (!value.images[0]) cb(new Error('至少选择一张封面图'))
      }
      if (value.type === 3) {
        if (!(value.images[0] && value.images[1] && value.images[2]))
          cb(new Error('至少需要3张封面图'))
      }
      cb()
    }
    return {
      // 发布信息
      articleForm: {
        title: '',
        cover: {
          // 封面
          type: 1,
          images: [],
        },
        channel_id: '',
        content: '',
      },
      // 图片上传
      dialogImageUrl: '',
      dialogVisible: false,
      baseURL, // 基础请求路径
      // 编辑器
      editor: null,
      // html: '<p>hello</p>',
      toolbarConfig: {},
      editorConfig: { placeholder: '请输入内容...' },
      mode: 'default', // or 'simple'
      // 表单文本校验规则
      articleRules: {
        title: [
          { required: true, message: '请输入标题', trigger: 'blur' },
          {
            min: 5,
            max: 40,
            message: '长度在 5 到 40 个字符',
            trigger: 'blur',
          },
        ],
        articleId: [
          { required: true, message: '频道为必选项', trigger: 'blur' },
        ],
        cover: [{ validator: checkCoverFn, trigger: 'change' }],
        content: [{ required: true, message: '请输入内容', trigger: 'blur' }],
      },
    }
  },
  computed: {
    ...mapGetters(['token']),
    fileList() {
      return this.articleForm.cover.images.map(item => ({
        name: item,
        url: item,
      }))
    },
  },
  // watch: {},
  // 钩子函数
  created() {
    if (this.articleId) this._getArticleDetail()
  },
  mounted() {
    // 模拟 ajax 请求，异步渲染编辑器
    /* setTimeout(() => {
      this.html = '<p>模拟 Ajax 异步设置内容 HTML</p>'
    }, 1500) */
  },
  beforeDestroy() {
    const editor = this.editor
    if (editor == null) return
    editor.destroy() // 组件销毁时，及时销毁编辑器
  },
  // @当前路由改变，但是该组件被复用时调用
  beforeRouteUpdate(to, from, next) {
    // console.log('组件被复用时调用', to, from, next)
    if (to.query.id) {
      this._getArticleDetail()
    } else {
      // 重置所有表单数据
      this.$refs.articleDom.resetFields()
    }
    next() // 同时，这里始终需要调用一次 next()，使路由继续跳转
  },
  methods: {
    // @图片单选组change后
    imageTypeChange(value) {
      // console.log('it?', value)
      this.articleForm.cover.type = value
      this.articleForm.cover.images = [] // 细节：清空后，原先的图片数组也清空
      this.$refs.imgageUpload && this.$refs.imgageUpload.clearFiles()
    },
    // @校验：手动触发图片校验
    validateCover() {
      this.$refs.articleDom.validateField('cover') // 手动调 图片栏校验
    },
    /**
     * @description: 文件上传成功时的钩子
     * @param {*} response
     * @param {*} file
     * @param {*} fileList
     * @return {*}
     */
    imageUploadSuccess(response) {
      // console.log('上传成功', response, file, fileList)
      this.$message({
        type: 'success',
        message: '文件上传成功',
      })
      const {
        data: { url },
      } = response
      this.articleForm.cover.images.push(url)
      this.validateCover()
    },
    /**
     * @description: 文件上传失败时的钩子
     * @param {*} response
     * @param {*} file
     * @param {*} fileList
     * @return {*}
     */
    imageUploadError() {
      // console.log('上传失败', response, file, fileList)
      this.$message({
        type: 'error',
        message: '文件上传失败',
      })
    },
    // @上传超出文件限制个数的钩子
    // tip: 不合理，应该在固定个数时直接去掉继续上传的按钮
    imageUploadExceed() {
      this.$message({
        type: 'warning',
        message: '上传文件个数已达上限',
      })
    },
    // @文件列表移除文件时的钩子
    imageUploadRemove(file) {
      // console.log('文件列表移除文件时', file, fileList)
      console.log('文件列表移除文件时', file)
      const url = file?.response?.data?.url || file?.url
      this.articleForm.cover.images.splice(
        this.articleForm.cover.images.indexOf(url),
        1
      )
      this.validateCover()
    },
    // @点击文件列表中已上传的文件时的钩子
    handlePictureCardPreview(file) {
      // console.log('点击文件列表中，已上传文件时的钩子', file)
      this.dialogImageUrl = file.url
      this.dialogVisible = true
    },
    onCreated(editor) {
      this.editor = Object.seal(editor) // 一定要用 Object.seal() ，否则会报错
    },
    // @发布文章
    _publicArticle(isSaveAsDraft) {
      this.$refs.articleDom.validate(async valid => {
        // console.log('校验是否通过?', valid)
        if (!valid) {
          return this.$message({
            type: 'error',
            message: '文章校验未通过',
          })
        } else {
          // 通过校验
          // console.log('当前参数', this.articleForm)
          // console.log('id 值类型', typeof this.articleForm.articleId)
          const [err] = await publishArticle(isSaveAsDraft, this.articleForm)
          // console.log('发布成功？', err, res)
          if (err) return this.$message.error('文章发表出错')
          this.$message.success('文章发表成功')
          this.$router.push('/article')
        }
      })
    },
    // @获取文章详情
    async _getArticleDetail() {
      const [err, res] = await getArticleDetail(this.articleId)
      console.log('获取文章详情', err, res)
      const {
        data: { channel_id, content, cover, title },
      } = res
      this.articleForm.channel_id = channel_id
      this.articleForm.content = content
      this.articleForm.cover = cover
      this.articleForm.title = title
    },
    // @修改文章
    async _modifiArticle(isSaveAsDraft) {
      this.$refs.articleDom.validate(async valid => {
        // console.log('校验是否通过?', valid)
        if (!valid) {
          return this.$message({
            type: 'error',
            message: '文章校验未通过',
          })
        } else {
          // console.log('修改文章')
          const [err] = await modifiArticleDetail(
            this.articleId,
            isSaveAsDraft,
            this.articleForm
          )
          if (err) this.$message.error('修改失败')
          this.$message.success('修改成功')
          this.$router.push('/article')
        }
      })
    },
  },
}
</script>

<style scoped lang="scss">
@import '@wangeditor/editor/dist/css/style.css';
.publish-container {
  ::v-deep .el-upload-list__item {
    transition: none;
  }
  ::v-deep .el-upload-list--picture-card {
    .el-upload-list__item-thumbnail {
      object-fit: contain;
    }
  }
}
</style>
